package com.example.websocket.ws;
import com.example.websocket.pojo.ws.GroupMessage;
import com.example.websocket.pojo.ws.ResultMessage;
import com.example.websocket.service.GroupService;
import com.example.websocket.utils.MessageUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpSession;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;


import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.example.websocket.constants.Constants.*;

/**
 * @ author 韩
 * time: 2024/3/24 16:51
 */
@ServerEndpoint(value = "/group",configurator = GetHttpSessionConfigurator.class)
@Slf4j
@Component
public class Group {
    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        Group.applicationContext = applicationContext;
    }

    // 用来存储每一个客户端对象对应的ChatEndpoint对象
    private static final Map<String,Group> onlineUsers = new ConcurrentHashMap<>();

    //声明session对象，通过该对象可以发送消息给指定的用户
    private Session session;
    //声明一个HttpSession对象，我们之前再HttpSession对象中存储了用户名
    private HttpSession httpSession;

    private StringRedisTemplate redisTemplate;
    private GroupService groupService;
    private String username;
    /**
     * 建立websocket连接后，被调用
     * @param session
     *
     * 改造一下主要是实现一个群聊的功能，该开始的群聊其实是伪群聊，因为他并没有创建群聊的操作，而是直接去遍历所有的用户
     *
     *
     */



    @OnOpen
    // 连接建立时被调用
    public void onOpen(Session session, EndpointConfig config) throws IOException {
        // 1.将局部的session进行保存
        this.session = session;
        // 2.获取httpSession对象
        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        // 3.将当前对象存储到容器中, 获取当前登录的用户
        username = (String) this.httpSession.getAttribute("username");
//        username = "user1";
        System.out.println(username + "group open");

        onlineUsers.put(username,this);
        // 把所有的redis里的消息遍历 发送到前端

        redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
        groupService = applicationContext.getBean(GroupService.class);


    }



    @OnMessage
    // 接收到客户端发送的数据时被调用
    public void onMessage(String message,Session session) {
        System.out.println(message);
           // 因为现在群聊作为一个选项存在 所以说得有多次初始化 刚进页面默认在群聊 onopen初始化了
           // 然后点击到群聊的时候直接触发方法发送一个init的key
        // 不需要了 因为刚点进群聊页面设置没有选中，就好了
        // message 有哪几种，判断一下做复用，message
        boolean flag = true;

        if (message.contains("\"")) {

            try {
                // 发过来一个对象，也是value能解析成功就证明要撤回这个消息
                ObjectMapper objectMapper = new ObjectMapper();
                ResultMessage message1 = objectMapper.readValue(message, ResultMessage.class);
            } catch (JsonProcessingException e) {
                flag = false;
            }
            if (flag) {
                //将传过来的message转换成ResultMessage对象
                ObjectMapper mapper = new ObjectMapper();

                ResultMessage mess = null;
                try {
                    mess = mapper.readValue(message, ResultMessage.class);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
                //获取要将数据发送给的用户
                String groupId = mess.getGroupId();
                String key = GROUP_KEY + groupId;
                String time = String.valueOf(mess.getTime());
                redisTemplate.opsForZSet().remove(key, message);

                // 在数据库里查一下 挨个遍历群聊里的用户，然后发送数据
                HashSet<String> set = groupService.getGroupUserList(groupId);

                // 这个的时间复杂度是群里的，可以比较一下谁大谁小，但这里体量较小 没什么区别就不演示了
                set.forEach(k -> {
                    if (onlineUsers.containsKey(k) && !Objects.equals(k,username)) {
                        try {
                            onlineUsers.get(k).session.getBasicRemote().sendText(time);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            } else {
                // 发送的正常消息
                GroupMessage groupMessage;
                try {
                    ObjectMapper objectMapper = new ObjectMapper();
                    groupMessage = objectMapper.readValue(message, GroupMessage.class);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }

                String groupId = groupMessage.getToGroupId();
                String data = groupMessage.getMessage();
                String key = GROUP_KEY + groupId;
                long currentTime = System.currentTimeMillis();
                String resultMessage = MessageUtils.getGroupMessage(username, groupId, data, currentTime);
                redisTemplate.opsForZSet().add(key,resultMessage,currentTime);
                // 在数据库里查一下 挨个遍历群聊里的用户，然后发送数据
                HashSet<String> set = groupService.getGroupUserList(groupId);

                // 这个的时间复杂度是群里的，可以比较一下谁大谁小，但这里体量较小 没什么区别就不演示了
                set.forEach(k -> {
                    if (onlineUsers.containsKey(k)) {
                        try {
                            onlineUsers.get(k).session.getBasicRemote().sendText(resultMessage);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });

                  // 这个的时间复杂度是登录的用户总数
//                onlineUsers.forEach((k,v) -> {
//                    if (set.contains(k)) {
//                        try {
//                            v.session.getBasicRemote().sendText(resultMessage);
//                        } catch (IOException e) {
//                            e.printStackTrace();
//                        }
//                    }
//                });

            }

        } else {
            System.out.println("群组第一次发的消息 初始化");
            String groupId = (String) httpSession.getAttribute(SESSION_GROUP_ID);



            String key = GROUP_KEY + groupId;
            Set range = redisTemplate.opsForZSet().range(key, 0, -1);
            System.out.println(key);
            System.out.println(range);
            // 在数据库里查一下 群聊里的用户 不需要查 初始化不需要

            range.forEach((v) -> {
                try {
                    this.session.getBasicRemote().sendText((String) v);
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            });
        }



    }

    @OnClose
    // 连接关闭时 被调用
    public void onClose(Session session) {
        System.out.println(username + "group close");
        onlineUsers.remove(username);
    }

}